let ws = require("ws");
let httpServ = require('https');
let fs = require('fs');
let CumulationID = require('../modules/id_alloter').CumulationID;

class WebsocketServer{
    constructor(name, port, ssl_key=null, ssl_crt=null){
        this.name = name;
        this.port = port;
        this.ssl = ssl_key?{ssl_key:ssl_key, ssl_cert:ssl_crt}:null;
        this.ids = new CumulationID();
        this.ids.init(10, 400000000);
        this.mapIds = new Map();
    }
    startWork(connectCallback, errorCallback, recvCallback, closeCallback){
        let self = this;
        if (this.ssl) {
            // 创建request请求监听器
            this.processRequest = (req, res) => {
                res.writeHead(200);
                res.end('This is WebSockets!\n');
            };
            // 创建https服务
            this.app = httpServ.createServer({
                // 向server传递key和cert参数
                key: fs.readFileSync(this.ssl.ssl_key),
                cert: fs.readFileSync(this.ssl.ssl_cert)
            }, this.processRequest);
            // 实例化WebSocket服务器
            this.server = new ws.Server({
                server: this.app
            });
            this.app.listen(this.port);
        } else {
            this.server = new ws.Server({
                port: self.port,
            });
        }
        // 错误事件
        this.server.on("error", function(err){
            if (global.log) {
                global.log.error(`${self.name} error ${err}`);
            } else {
                console.error(`${self.name} error ${err}`);
            }
        });
        // html头事件
        // this.server.on("headers", function(data){
        //     // console.log(data);
        // });
        // 监听成功事件
        this.server.on("listening", function(){
            if (global.log) {
                global.log.print(`port:${self.port} ${self.name} listening...`);
            } else {
                console.log(`port:${self.port} ${self.name} listening...`);
            }
        });
        // 客户端接入事件
        this.server.on("connection", function(socket){
            socket.on("close", function() {
                // console.log("client close");
                if (closeCallback) {
                    closeCallback(this);
                }
                self.mapIds.delete(socket.conn_id);
            });
            socket.on("error", function(err) {
                if (global.log) {
                    global.log.error(`${self.name} socket error ${err}`);
                } else {
                    console.error(`${self.name} socket error ${err}`);
                }
                if (errorCallback) {
                    errorCallback(this, err);
                }
            });
            socket.on("message", function(data) {
                // console.log(data);
                if (recvCallback) {
                    recvCallback(this, data);
                }
            });

            socket.conn_id = self.ids.getID();
            self.mapIds.set(socket.conn_id , socket);
            // console.log("new client");
            if (connectCallback) {
                connectCallback(socket);
            }
        });
    }
    findSocket(connId){
        return this.mapIds.get(connId);
    }
    send(connId, data){
        let socket = this.mapIds.get(connId);
        if (socket) {
            try {
				socket.send(data);
				return true;
			} catch (err) {
				if (global.log) {
					global.log.error(`${this.name} socket error ${err}`);
				} else {
					console.error(`${this.name} socket error ${err}`);
				}
				return false;
			}
        }
        return false;
    }
    massSend(connIds, data){
        if (connIds.length) {
            for (let i = 0; i < connIds.length; i++) {
                this.send(connIds[i], data);
            }
        }
    }
    closeSocket(connId){
        let socket = this.mapIds.get(connId);
        if (socket) {
            try {
				socket.close();
				return true;
			} catch (err) {
				if (global.log) {
					global.log.error(`${this.name} socket error ${err}`);
				} else {
					console.error(`${this.name} socket error ${err}`);
				}
				return false;
			}
        }
        return false;
    }
}

module.exports = WebsocketServer;